#! /bin/sh
:
# Copyright (c) 1990-1997, S.R. van den Berg, The Netherlands
# Copyright (c) 1999-2001, Philip Guenther, The United States of America
#$Id: autoconf,v 1.122.2.5 2001/07/16 06:58:19 guenther Exp $

# All possible entries in autoconf.h:

#	#define UNISTD_H_MISSING
#	#define STDDEF_H_MISSING
#	#define STDLIB_H_MISSING
#	#define DIRENT_H_MISSING
#	#define SYS_DIRENT_H_MISSING
#	#define NDIR_H_MISSING
#	#define SYS_NDIR_H_MISSING
#	#define SYS_DIR_H_MISSING
#	#define SYS_WAIT_H_MISSING
#	#define SYS_UTSNAME_H_MISSING
#	#define STRING_H_MISSING
#	#define SYSEXITS_H_MISSING
#Ok	#define SYS_FILE_H_MISSING
#Ok	#define SYSLOG_H_MISSING
#	#define MATH_H_MISSING
#	#define LIMITS_H_MISSING
#	#define NO_const
#	#define volatile
#	#define P(args) ()
#	#define NO_enum
#	#define void char
#	typedef int mode_t;
#	typedef int pid_t;
#	typedef int uid_t;
#	typedef int gid_t;
#	typedef unsigned size_t;
#	typedef long off_t;
#	typedef long time_t;
#	#define NOmemmove
#Ok	#define NObcopy
#	#define NOstrcspn
#	#define NOstrpbrk
#	#define NOopendir
#	#define NOrename
#	#define NOsetrgid
#	#define NOsetegid
#	#define NOsetregid
#	#define NOsetresgid
#	#define setrgid_BRAIN_DAMAGE
#	#define setrgid_RUNTIME_CHECK
#Ok	#define TOGGLE_SGID_OK
#	#define NOpow
#	#define NOmkdir
#	#define NOfstat
#	#define NOuname
#	#define NO_exit
#	#define NOstrtol
#	#define NOstrtod
#	#define NOstrerror
#Ok	#define NOstrlcat
#Ok	#define NOstrncasecmp
#Ok	#define NOsys_errlist
#Ok	#define NObzero
#	#define NOmemset
#	#define NOwaitpid
#Ok	#define NOftruncate
#	#define SLOWstrstr
#Ok	#define CAN_chown
#	#define strchr(s,c) index(s,c)
#	#define NOinitgroups
#	#define NOfsync
#Ok	#define endpwent()
#Ok	#define endgrent()
#Ok	#define endhostent()
#Ok	#define endservent()
#Ok	#define endprotoent()
#	#define h_0addr_list h_addr
#Ok	#define NOpw_passwd
#Ok	#define NOpw_class
#Ok	#define NOpw_gecos
#Ok	#define NO_COMSAT
#	#define _GUID_T
#Ok	#define UDP_protocolno 17
#Ok	#define BIFF_serviceport "512"
#Ok	#define IP_localhost {127,0,0,1}
#	#define WMACROS_NON_POSIX
#	#define oBRAIN_DAMAGE
#Ok	#define GOT_bin_test
#Ok	#define MAX_argc 128
#Ok	#define MAX_envc 128
#Ok	#define SMALLHEAP
#	#define NOfcntl_lock
#Ok	#define USElockf
#Ok	#define USEflock
#Ok	#define MAILSPOOLDIR "/var/spool/mail/"
#Ok	#define SENDMAIL "/usr/sbin/sendmail"
#	#define buggy_SENDMAIL
#	#define DEFflagsendmail ""
#Ok	#define CF_no_procmail_yet
#Ok	#define defSPATH "PATH=/bin:/usr/bin:/usr/local/bin"
#Ok	#define defPATH "PATH=$HOME/bin:/bin:/usr/bin:/usr/local/bin"
#Ok	#define INEFFICIENTrealloc
#Ok	#define PM_VERSION "n.nn"

# A conforming ISO C compiler and POSIX library should not have any defines
# not marked as "Ok" in the autoconf.h file.
# Anything else indicates failure of your system to comply with either
# the ISO or POSIX standards (but procmail should be installable anyway).

if test -z "$IFS"
then IFS=" \
	\

"
  export IFS
fi

SHELL=$1
PATH=.:$PATH
shift; RM="$1"
shift; MV="$1"
shift; DEVNULL=$1
shift; FGREP="$1"
shift; MAKE="$1"
shift; O=$1
shift; LOCKINGTEST="$1"
shift; BINDIR=$1
shift; ACONF=$1

test 1 != $# &&
 echo "Don't start this script directly, use \`make ../autoconf.h'" && exit 1

if test -f make_n
then
  $RM make_n
else
  # We were mistakenly invoked under "make -n", so pretend this didn't happen.
  exit 0
fi

export SHELL PATH

test "X$LOCKINGTEST" = X__defaults__ && LOCKINGTEST=""

OLDTESTDIRS=""
tailpid=""
echo "" >_locktst.pid

if test -f $ACONF
then
  if $FGREP -e "/* autoconf completed */" $ACONF >$DEVNULL
  then
     cat <<HERE
==============================================================================
Would you like to skip running autoconf and use the existing autoconf.h file?
When in doubt, press return [n]:
HERE
     read a
     case "$a"n in
	[yY]*) touch $ACONF; exit 0;;
     esac
  fi
  trap "kill \`cat _locktst.pid\` 2>$DEVNULL;cp $ACONF $ACONF.tmp
   test ! -z \"\$OLDTESTDIRS\" && $RM -r \$OLDTESTDIRS \$OLDTESTDIRS 2>$DEVNULL
   test ! -z \"\$tailpid\" && kill \$tailpid 2>$DEVNULL
   kill \`cat _locktst.pid\` 2>$DEVNULL; exit 1" 1 2 3 13 15
else
  trap "kill \`cat _locktst.pid\` 2>$DEVNULL;$RM -r $ACONF.tmp
   test ! -z \"\$OLDTESTDIRS\" && $RM -r \$OLDTESTDIRS \$OLDTESTDIRS 2>$DEVNULL
   mv $ACONF $ACONF.tmp 2>$DEVNULL
   test ! -z \"\$tailpid\" && kill \$tailpid 2>$DEVNULL
   kill \`cat _locktst.pid\` 2>$DEVNULL; exit 1" 1 2 3 13 15
fi

nocore=yes
set dummy *core*
test -f $2 && nocore=no

set dummy $LOCKINGTEST
shift
LOCKINGTEST="$*"

test ! -z "$LOCKINGTEST" && exec 9>&1 1>$DEVNULL	# make it shut up

cat <<HERE
==============================================================================
In order for the kernel-locking tests to work as intended I have to be able to
test-lock files on as many semantically different filesystems as possible (for
more information about this, READ PARAGRAPH TWO in INSTALL).  To suppress this
prompt you can set the LOCKINGTEST variable in the Makefile.

Please add writable directories to the list.  You should only add directories
that reside on filesystems that have unique characteristics.  E.g. if you have
several remote NFS partitions, pick some unique client-server pairs, there is
little use in picking the same server twice from the same client-machine.
An excellent candidate would be a remotely mounted mail spool directory.
==============================================================================
HERE

testdirs="/tmp ."

case "$LOCKINGTEST" in
  ""|*[a-zA-Z/]*) b=dummy ;;
  *) b=""; testdirs=$LOCKINGTEST; LOCKINGTEST=dummy ;;
esac

while test ! -z "$b"
do
  echo ""
  b=""
  OLDTESTDIRS="$TESTDIRS"
  TESTDIRS=""
  for a in $testdirs
  do $RM -r $a/_locktest
     if mkdir $a/_locktest 2>$DEVNULL
     then
	b="$b $a"
	TESTDIRS="$TESTDIRS $a/_locktest"
     else
	echo 2>&1 "Can't create $a/_locktest"
     fi
  done
  OLDTESTDIRS="$TESTDIRS"
  testdirs="$b"
  echo ""
  echo "I will temporarily use a testdirectory named _locktest"
  echo "in the following directories:"
  echo ""
  echo $testdirs
  echo ""
  echo "If you would like to add any, please specify them below,"
  echo "press return to continue:"
  echo ""
  if test -z "$LOCKINGTEST"
  then
     read b
  elif test dummy = "$LOCKINGTEST"
  then
     b=""
  else
     testdirs=""; b="$LOCKINGTEST"; LOCKINGTEST=dummy
     echo $b
  fi
  testdirs="$testdirs $b"
done

if test dummy = "$LOCKINGTEST"
then
   exec 1>&9 9>&-					# you can speak again
   echo "Using the following directories for the LOCKINGTESTs:"
   echo " $testdirs"
fi

cat >grepfor <<HERE
$FGREP -e "\$1" _autotst.rrr >$DEVNULL && echo "\$2" >>$ACONF
HERE
chmod 0755 grepfor

cat >$ACONF <<HERE
/* This file was automagically generated by autoconf */

HERE

echo >_locktst.h

$RM _autotst.$O

cat >_autotst.c <<HERE
#include "$ACONF"
#include <sys/types.h>
#include <time.h>
void*vvoid;
int main(){int i=0;char*p="t";
 vvoid=p;
 {time_t vtime;i+=vtime=1;}
 {off_t voff;i+=voff=1;}
 return !vvoid+!i;}
#include <unistd.h>
int empty()
{ return setsid();
}
HERE

if $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
 test -f _autotst.$O
then
  $MAKE _autotst >$DEVNULL 2>&1 || echo "#define setsid()" >>_locktst.h
else
  grepfor void '#define void char'
  grepfor time_t 'typedef long time_t;'
  grepfor off_t 'typedef long off_t;'
  if $MAKE _autotst.$O >$DEVNULL 2>&1
  then
     $MAKE _autotst >$DEVNULL 2>&1 || echo "#define setsid()" >>_locktst.h
  else
     echo "#define UNISTD_H_MISSING" >>$ACONF
     echo "#define setsid()" >>_locktst.h
  fi
fi

$RM _autotst.$O _autotst

cat >_autotst.c <<HERE
#include "$ACONF"
#include <sys/types.h>
#ifndef UNISTD_H_MISSING
#include <unistd.h>
#endif
#include <fcntl.h>
#ifndef SYS_FILE_H_MISSING
#include <sys/file.h>
#endif
int main(){
#ifdef F_SETLKW
 fcntl(0,F_SETLKW,0);
#endif
#ifdef F_LOCK
  lockf(0,F_LOCK,(off_t)0);
#endif
#ifdef LOCK_EX
  flock(0,LOCK_EX);
#endif
 return 0;}
HERE

echo 'Initiating fcntl()/kernel-locking-support tests'
if $MAKE _autotst.$O >$DEVNULL 2>&1
then
:
else
  $RM _autotst.$O
  echo "#define SYS_FILE_H_MISSING" >>$ACONF
  if $MAKE _autotst.$O >_autotst.rrr 2>&1
  then
  :
  else
     echo 2>&1 "Whoeaaa!  There's something fishy going on here."
     echo 2>&1 "You have a look and see if you detect anything uncanny:"
     echo 2>&1 "*******************************************************"
     cat 2>&1 _autotst.rrr
     echo 2>&1 "*******************************************************"
     echo 2>&1 "I suggest you take a look at the definition of CFLAGS* and CC"
     echo 2>&1 "in the Makefile before you try make again."
     kill -15 $$
  fi
fi
$MAKE _autotst >_autotst.rrr 2>&1
$RM _autotst.$O _autotst

$FGREP fcntl _autotst.rrr >$DEVNULL && echo "#undef F_SETLKW" >>_locktst.h
$FGREP lockf _autotst.rrr >$DEVNULL && echo "#undef F_LOCK" >>_locktst.h
$FGREP flock _autotst.rrr >$DEVNULL && cat >>_locktst.h <<HERE
#ifdef LOCK_EX
#undef LOCK_EX
#endif
#ifndef SYS_FILE_H_MISSING
#define SYS_FILE_H_MISSING
#endif
HERE

cat >_autotst.c <<HERE
#include "$ACONF"
#include "../config.h"
#include <sys/types.h>
#ifndef UNISTD_H_MISSING
#include <unistd.h>		/* getpid() getppid() */
#endif
#include <stdio.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>		/* SIGKILL */
#ifndef tell
#define tell(fd)	lseek(fd,(off_t)0,SEEK_CUR)
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS	0
#endif
#include "_locktst.h"
#ifndef SYS_FILE_H_MISSING
#include <sys/file.h>
#endif
#ifndef SEEK_SET
#define SEEK_SET	0
#define SEEK_CUR	1
#define SEEK_END	2
#endif

#define MIN_locks	128	  /* minimum of consecutive successful locks */
#define SLEEP_loop	64		      /* iterations in the busy loop */
#define SLEEP_delay	0		  /* sleep() time per busy iteration */
#define SLEEP_retreat	1		 /* extra sleep() when quota reached */
#define TIME_OUT_SEC	16			 /* initial timeout per lock */
#define NR_of_forks	8			 /* concurrent test-programs */
#define NR_of_lockfiles 2		  /* lockfiles used in testing (<=4) */
#define GROW		3			    /* when timing got worse */
#define DECAY		7/8			   /* when timing got better */
#define GOBBLE		256			 /* for the SunOS crash test */

#define LOCKS_per_child (((MIN_locks+NR_of_forks-1)/NR_of_forks+1)/2)
#define SHIFT_childno	3
#define MASK_fileno	((1<<SHIFT_childno)-1)
#define MASK_childno	(~MASK_fileno)

#ifdef NO_fcntl_LOCK
#undef F_SETLKW
#endif
#ifdef NO_lockf_LOCK
#undef F_LOCK
#endif
#ifdef NO_flock_LOCK
#undef LOCK_EX
#endif

#define FIRST_lock	0x04		/* testing is in order of importance */
#define MSK_fcntl	0x04	       /* don't change this order unless you */
#define MSK_lockf	0x02	       /* change locking.c as well, fdlock() */
#define MSK_flock	0x01			 /* and hotwired LOCKINGTEST */

int dolock,child[NR_of_forks],timeout,fdcollect;
char dirlocktest[]="_locktest";

void stimeout()
{ timeout=1;close(fdcollect);killchildren();
}

void Terminate()
{ stimeout();exit(1);
}

static unsigned long seed;

unsigned psrand()
{ return (unsigned)(seed*=69069L)>>8;
}

unsigned sfork()
{ int pid;
  while((pid=fork())<0)
     fprintf(stderr,"Couldn't fork _locktst, retrying\n"),sleep(TIME_OUT_SEC);
  return pid;
}

int main(argc,argv)char*argv[];
{ int goodlock,testlock,i,pip[2],pipw[2];time_t otimet;unsigned dtimet;
  static char filename[]="_locktst.l0";
  close(0);goodlock=0;testlock=FIRST_lock;signal(SIGPIPE,SIG_DFL);
  if(argc==2)
   { char*p;
     for(p=argv[1];;)
      { switch(*p++)					/* parse the hotwire */
	 { case '1':goodlock<<=1;goodlock++;
	      continue;
	   case '0':goodlock<<=1;
	      continue;
	   case '\0':
#ifndef F_SETLKW			/* sanity check, for the less gifted */
	      goodlock&=~MSK_fcntl;
#endif
#ifndef F_LOCK
	      goodlock&=~MSK_lockf;
#endif
#ifndef LOCK_EX
	      goodlock&=~MSK_flock;
#endif
	      goto skip_tests;
	 }
	break;						 /* oops, no hotwire */
      }
     goodlock=0;
   }
  if(sfork())				 /* try to ditch the controlling tty */
     return EXIT_SUCCESS;      /* to prevent rather messy kernel-diagnostics */
  setsid();				       /* from appearing on your tty */
  fprintf(stderr,"\
Every two digits a file is locked.  First digit: which file, second digit:\n\
which program, XX indicates a lock conflict or failure\n");
  do
   { int countlocks;
     signal(SIGTERM,SIG_DFL);argc=1;dolock=goodlock|testlock;
     do
      { char*curdir;
	curdir=argv[argc];otimet=time((time_t*)0);
	if(sfork())
	 { close(1);close(2);i=NR_of_lockfiles;chdir(curdir);
	   chdir(dirlocktest);
	   do			       /* prime the lock, see if it vanishes */
	    { filename[sizeof filename-2]='0'+--i;
	      lseek(goodlock=open(filename,O_WRONLY),(off_t)0,SEEK_END);
	      fdlock(goodlock);
	    }
	   while(i);
	   for(;;)				/* synchronising "busy"-wait */
	      sleep(TIME_OUT_SEC);	   /* until the games can be started */
	 }
	sleep(1);pipe(pip);pipe(pipw);i=NR_of_forks;*child=0;
	fprintf(stderr,"\nStarting test %x on %s\n",dolock,curdir);
	while((child[--i]=sfork())&&i);		       /* divide and conquer */
	if(!*child)
	 { unsigned char lockflag;int fd,childno=i<<SHIFT_childno;
	   int mylocks=LOCKS_per_child;
	   close(pipw[0]);close(pip[0]);close(1);
	   seed=time((time_t*)0)+getpid()|1;chdir(curdir);chdir(dirlocktest);
	   close(pipw[1]);
	   for(;;)					   /* and lock away! */
	    { filename[sizeof filename-2]='0'+(i=psrand()%NR_of_lockfiles);
	      lockflag=childno|i<<1|1;
	      lseek(fd=open(filename,O_WRONLY),(off_t)0,SEEK_END);
	      if(sfdlock(fd))
		 lockflag&=~1,fprintf(stderr,"XX%x",lockflag);
	      write(pip[1],&lockflag,1);
	      fprintf(stderr," %x%x",i,childno>>SHIFT_childno);
	      lseek(fd,(off_t)0,SEEK_END);write(fd,&lockflag,1);
	      for(i=SLEEP_loop;i;i--,time((time_t*)0),sleep(SLEEP_delay));
	      lockflag&=~1;write(pip[1],&lockflag,1);
	      if(fdunlock()||close(fd))
	       { write(pip[1],&lockflag,1);fprintf(stderr,"XX%x",lockflag);
		 return 1;
	       }
	      if(--mylocks<0)
		 sleep(SLEEP_retreat);
	    }
	 }
	signal(SIGTERM,Terminate);
	;{ unsigned char lckdfil[NR_of_lockfiles],curflag;
	   int j,ppid;			       /* give all children a chance */
	   ppid=getppid();
	   if(sfork())	/* discard the old body, let init adopt our children */
	      return EXIT_SUCCESS;
	   ;{ FILE*fp;
	      if(fp=fopen("_locktst.pid","w"))
		 fprintf(fp,"%ld",(long)getpid()),fclose(fp);
	    }
	   countlocks=MIN_locks;close(pip[1]);close(pipw[1]);
	   for(j=NR_of_lockfiles;lckdfil[--j]=0,j;);
	   timeout=0;sleep(1);read(pipw[0],&curflag,1);close(pipw[0]);
	   kill(ppid,SIGKILL);fdcollect=pip[0];signal(SIGALRM,stimeout);
	   dtimet=(time((time_t*)0)-otimet)*GROW+TIME_OUT_SEC;
	   do
	    { unlink("_locktst.alive");alarm(dtimet+2);		 /* watchdog */
	      dtimet=(otimet=time((time_t*)0)-otimet)>dtimet?
	       otimet*GROW:otimet+(dtimet-otimet)*DECAY+1; /* load dependent */
	      otimet=time((time_t*)0);
	    }
	   while(1==read(fdcollect,&curflag,1)&&
	    (j=lckdfil[i=(curflag&MASK_fileno)>>1],!timeout)&&
	    ((j^(lckdfil[i]=curflag))==1||!(j&1)&&curflag&1)&&--countlocks);
	   alarm(0);close(fdcollect);killchildren();
	   fprintf(stdout,
	    "/*locktype: %x, countlocks: %x, timeout %x, watchdog %x, %s*/\n",
	    dolock,countlocks,timeout,dtimet,curdir);fflush(stdout);
	 }
      }
     while(!countlocks&&argv[++argc]);
     if(!countlocks)			    /* Hurray!	Locking was flawless */
	goodlock=dolock;			  /* make a mark on our colt */
   }
  while(testlock>>=1);
skip_tests:
  printf("/* Hotwire LOCKINGTEST=%c%c%c */\n",goodlock&0x4?'1':'0',
   goodlock&0x2?'1':'0',goodlock&0x1?'1':'0');
  printf("/* Procmail will lock via: dotlocking");    /* report our findings */
  if(goodlock&MSK_fcntl)
     printf(", fcntl()");
  if(goodlock&MSK_lockf)
     printf(", lockf()");
  if(goodlock&MSK_flock)
     printf(", flock()");
  puts(" */");
  if(!(goodlock&MSK_fcntl))		   /* and in machine readable format */
     puts("#define NOfcntl_lock");
  if(goodlock&MSK_lockf)
     puts("#define USElockf");
  if(goodlock&MSK_flock)
   { puts("#define USEflock");
#ifdef SYS_FILE_H_MISSING
     puts("#define SYS_FILE_H_MISSING");
#endif
   }
  puts("Kernel-locking tests completed.");fprintf(stderr,"\n");
  return EXIT_SUCCESS;
}

int killchildren()
{ int i;
  i=NR_of_forks;
  do
     if(child[--i]>0)
	kill(child[i],SIGTERM),child[i]=0;
  while(i);
  return 0;
}

int sfdlock(fd)
{ int i;unsigned gobble[GOBBLE>>2];
  for(i=GOBBLE>>2;i;gobble[--i]=~(unsigned)0);		 /* SunOS crash test */
  return fdlock(fd);
}

static oldfdlock;
#ifdef F_SETLKW
static struct flock flck;		/* why can't it be a local variable? */
#endif
#ifdef F_LOCK
static off_t oldlockoffset;
#endif

int fdlock(fd)
{ int i;unsigned gobble[GOBBLE>>2];
  for(i=GOBBLE>>2;i;gobble[--i]=~(unsigned)0);		 /* SunOS crash test */
  oldfdlock=fd;fd=0;
  if(MSK_fcntl&dolock)
#ifdef F_SETLKW
   { static unsigned extra;
     flck.l_type=F_WRLCK;flck.l_whence=SEEK_SET;flck.l_start=tell(oldfdlock);
     if(!extra--)
	extra=MIN_locks/4,flck.l_len=2,i|=fcntl(oldfdlock,F_SETLK,&flck);
     flck.l_len=0;fd|=fcntl(oldfdlock,F_SETLKW,&flck);
   }
#else
     fd=1;
#endif
  if(MSK_lockf&dolock)
#ifdef F_LOCK
     oldlockoffset=tell(oldfdlock),fd|=lockf(oldfdlock,F_LOCK,(off_t)0);
#else
     fd=1;
#endif
  if(MSK_flock&dolock)
#ifdef LOCK_EX
     fd|=flock(oldfdlock,LOCK_EX);
#else
     fd=1;
#endif
  return fd;
}

int fdunlock()
{ int i;unsigned gobble[GOBBLE];
  for(i=GOBBLE;i;gobble[--i]=~(unsigned)0);  /* some SunOS libs mess this up */
  if(MSK_flock&dolock)
#ifdef LOCK_EX
     i|=flock(oldfdlock,LOCK_UN);
#else
     i=1;
#endif
  if(MSK_lockf&dolock)
#ifdef F_LOCK
   { lseek(oldfdlock,oldlockoffset,SEEK_SET);
     i|=lockf(oldfdlock,F_LOCK,(off_t)2);i|=lockf(oldfdlock,F_ULOCK,(off_t)0);
   }
#else
     i=1;
#endif
  if(MSK_fcntl&dolock)
#ifdef F_SETLKW
     flck.l_type=F_UNLCK,flck.l_len=0,i|=fcntl(oldfdlock,F_SETLK,&flck);
#else
     i=1;
#endif
  if(!i)
     for(i=GOBBLE;i&&gobble[--i]==~(unsigned)0;);
  return i;
}
HERE

if $MAKE _autotst >_autotst.rrr 2>&1
then
:
else
  echo 2>&1 "Whoeaaa!  There's something fishy going on here."
  echo 2>&1 "You have a look and see if you detect anything uncanny:"
  echo 2>&1 "*******************************************************"
  cat 2>&1 _autotst.rrr
  echo 2>&1 "*******************************************************"
  echo 2>&1 "I suggest you take a look at the definition of LDFLAGS*"
  echo 2>&1 "in the Makefile before you try make again."
  kill -15 $$
fi

$MV _locktst _locktst.$$ 2>$DEVNULL
$RM _autotst.$O _autotst.rrr _locktst* 2>$DEVNULL
echo "" >_locktst.pid
$MV _autotst _locktst

case "$testdirs" in
  *[a-zA-Z/]*)
     for b in $TESTDIRS
     do
	for a in 0 1 2 3
	do echo dummy_file >$b/_locktst.l$a
	done
     done ;;
  *) TESTDIRS=$testdirs ;;
esac

echo 2>&1 ""

_locktst $TESTDIRS >_locktst.rrr 2>lock.log	# will finish in the background
echo 'Proceeding with kernel-locking-support tests in the background'


cat >_autotst.c <<HERE
#include "$ACONF"
#ifndef UNISTD_H_MISSING
#include <unistd.h>		/* execvp() */
#endif
int a(b)const int b[];
{ return *++b;				  /* watcom 10.6 on QNX refuses this */
}
int main()
{ char r[]="",*const*p;char*q="";const char*s="";
  static const char*const nullp=0,*const*d= &nullp;	/* AIX 3.2.3 failure */
  static struct{const int a;int b;}c[2]={{0,0},{0,0}};/* IRIX 7.3.1 compiler */
			    /* requires initializers on static const objects */
  --(c+1)->b;				 /* AIX 3.1.5 machines can't do this */
  p= &q;
  ;{ int pip[2];
     pipe(pip);
     if(fork())		       /* this should hide core dumps from the shell */
      { close(pip[1]);				    /* close the writing end */
	return 1==read(pip[0],r,1)?0:1;		   /* wait for the rendevouz */
      }
     close(pip[0]);				    /* close the writing end */
     if(!*d&&c[1].b)		      /* some magic to confuse the optimiser */
	d=(const char*const*)p;		     /* core dumps Ultrix 4.3 ANSI C */
     else /* so that it can't complain about the uselessness of this program */
	execvp(q,p);   /* IRIX 4.0.1 system-includes are wrong on this point */
     if(write(pip[1],r,1)!=1)		      /* notify mam that we survived */
	return 1;				   /* oops, lost mam somehow */
   }
  return r==s;		    /* Domain/OS warns here, not about "r==s" though */
}
HERE

echo 'Testing for const'
if $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
  test -f _autotst.$O && $MAKE _autotst >$DEVNULL 2>&1 && _autotst
then
  grepfor const '#define NO_const'
else
  echo '#define NO_const' >>$ACONF
  set dummy *core*
  if test -f $2 -a $nocore = yes
  then
     echo "Removing core file (bogus readonly segment)"
     $RM *core*
  fi
fi
$RM _autotst.$O _autotst

cat >_autotst.c <<HERE
int main(){volatile int i;return (i=0);}
HERE

echo 'Testing for volatile'
if $MAKE _autotst.$O >$DEVNULL 2>&1 && test -f _autotst.$O
then
:
else
 echo '#define volatile' >>$ACONF
 not_ISO=yep
fi
$RM _autotst.$O

if $FGREP NO_const $ACONF >$DEVNULL
then
  echo '#define P(args) ()' >>$ACONF
  not_ISO=yep
else
  cat >_autotst.c <<HERE
int main(const int argc,const char*const argv[]){return argc;}
HERE

  echo 'Testing for prototypes'
  if $MAKE _autotst.$O >$DEVNULL 2>&1 && test -f _autotst.$O
  then
  :
  else
     echo '#define P(args) ()' >>$ACONF
     not_ISO=yep
  fi
  $RM _autotst.$O
fi

cat >_autotst.c <<HERE
enum foo { A, B, C, D=7, E, F= -3, G };
int main(){return !(A==0&&B==1&&C==2&&D==7&&E==8&&F==-3&&G==-2);}
HERE

echo 'Testing for enum'
if $MAKE _autotst.$O >$DEVNULL 2>&1 && test -f _autotst.$O &&
   $MAKE _autotst >$DEVNULL 2>&1 && _autotst
then
:
else
 echo '#define NO_enum' >>$ACONF
 not_ISO=yep
fi
$RM _autotst.$O

if test -n "$not_ISO"
then
  cat <<HERE

Your system appears to not (correctly) support at least one of:
const, volatile, function prototypes, and enum types.  Future
versions of procmail will probably require support for all of them,
so you should either upgrade your compiler to one that's compliant
with the ISO C standard (the standard's over 10 years old, for
goodness sake), or send email to <bug@procmail.org> explaining why
you need procmail to continue to support K&R C.

HERE
fi

echo 'Checking for POSIX and ANSI/ISO system include files'

cat >_autotst.c <<HERE
#include "includes.h"
int a;
#ifndef SYS_DIRENT_H_MISSING
typedef DIR*tDIR;
tDIR vDIR;
#endif
HERE

i0="";i1="";i2="";i3="";i4="";i5="";i6="";i7="";i8="";i9="";i10="";i11="";
i12="";i13=""
oldi=""

while $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
 test ! -f _autotst.$O
do
  test -z "$i0" && grepfor stddef.h "#define STDDEF_H_MISSING" && i0=I
  test -z "$i1" && grepfor stdlib.h "#define STDLIB_H_MISSING" && i1=I
  test -z "$i2" && grepfor dirent.h "#define DIRENT_H_MISSING" && i2=I
  test -z "$i2" && grepfor DIR "#define DIRENT_H_MISSING		   \
/* <dirent.h> is there, but empty */" && i2=I
  test -z "$i3" && grepfor ndir.h "#define NDIR_H_MISSING" && i3=I
   test I = "$i3$i4" && grepfor sys/ndir.h "#define SYS_NDIR_H_MISSING" && i4=I
    test I = "$i4$i5" && grepfor sys/dir.h "#define SYS_DIR_H_MISSING" && i5=I
     test I = "$i5$i6" && grepfor sys/dirent.h "#define SYS_DIRENT_H_MISSING" \
      && i6=I
  test -z "$i7" && grepfor sys/wait.h "#define SYS_WAIT_H_MISSING" && i7=I
  test -z "$i8" && grepfor sys/utsname.h "#define SYS_UTSNAME_H_MISSING" &&
   i8=I
  test -z "$i9" && grepfor string.h "#define STRING_H_MISSING" && i9=I
  test -z "$i10" && grepfor sysexits.h "#define SYSEXITS_H_MISSING" && i10=I
  test -z "$i11" && grepfor math.h "#define MATH_H_MISSING" && i11=I
  test -z "$i12" && grepfor limits.h "#define LIMITS_H_MISSING" && i12=I
  test -z "$i13" && grepfor syslog.h "#define SYSLOG_H_MISSING" && i13=I
  newi="$i0$i1$i2$i3$i4$i5$i6$i7$i8$i9$i10$i11$i12$i13"
  if test a$oldi = a$newi
  then
     echo 2>&1 "Whoeaaa!  There's something fishy going on here."
     echo 2>&1 "You have a look and see if you detect anything uncanny:"
     echo 2>&1 "*******************************************************"
     $MAKE _autotst.$O >_autotst.rrr 2>&1
     cat 2>&1 _autotst.rrr
     echo 2>&1 "*******************************************************"
     echo 2>&1 "I suggest you take a look at the definition of CFLAGS*"
     echo 2>&1 "in the Makefile before you try make again."
     kill -15 $$
  fi
  oldi=$newi
  echo \
   "	...missing `expr $oldi : '.*'` include files, doublechecking..."
done

$RM _autotst.$O

cat >_autotst.c <<HERE
#include "includes.h"
#include "network.h"
int a;
HERE

echo 'Checking for network/comsat/biff support'

if $MAKE _autotst.$O >$DEVNULL 2>&1
 test -f _autotst.$O
then
:
else
  echo "#define NO_COMSAT" >>$ACONF
fi

$RM _autotst.$O

cat >_autotst.c <<HERE
#include "includes.h"
#ifndef NO_COMSAT
#include "network.h"
#endif
int main(){int i=0;
 {size_t vsize_t;i+=vsize_t=1;}
 {pid_t vpid_t;i+=vpid_t=1;}
 {mode_t vmode_t;i+=vmode_t=1;}
 {uid_t vuid_t;i+=vuid_t=1;}
 {gid_t vgid_t;i+=vgid_t=1;}
#ifndef NO_COMSAT
 {struct hostent vhostent;i+=!(vhostent.h_addr_list=0);}
#endif
#ifndef NOuname
 {struct utsname vutsname;i+=!(*vutsname.nodename='\0');}
#endif
 return !i;}
HERE

echo 'Testing for void*, size_t, off_t, pid_t, time_t, mode_t, uid_t & gid_t'

i1="";i2="";i3="";i4="";i5="";i6="";i7=""
oldi=""

while $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
 test ! -f _autotst.$O
do
  test -z "$i1" && grepfor size_t 'typedef unsigned size_t;' && i1=I
  test -z "$i2" && grepfor pid_t 'typedef int pid_t;' && i2=I
  test -z "$i3" && grepfor mode_t 'typedef int mode_t;' && i3=I
  test -z "$i4" && grepfor uid_t 'typedef int uid_t;' && i4=I
  test -z "$i5" && grepfor gid_t 'typedef int gid_t;' && i5=I
  test -z "$i6" && grepfor h_addr_list '#define h_0addr_list h_addr' && i6=I
  test -z "$i6" && grepfor hostent '#define h_0addr_list h_addr' && i6=I
  test -z "$i6" && grepfor member '#define h_0addr_list h_addr' && i6=I
  test -z "$i7" && grepfor utsname "#define NOuname			      \
/* <sys/utsname.h> is there, but empty */" && i7=I
  newi="$i1$i2$i3$i4$i5$i6$i7"
  if test a$oldi = a$newi
  then
     echo 2>&1 "Whoeaaa!  There's something fishy going on here."
     echo 2>&1 "You have a look and see if you detect anything uncanny:"
     echo 2>&1 "*******************************************************"
     $MAKE _autotst.$O >_autotst.rrr 2>&1
     cat 2>&1 _autotst.rrr
     echo 2>&1 "*******************************************************"
     echo 2>&1 "I suggest you take a look at the definition of CFLAGS*"
     echo 2>&1 "in the Makefile before you try make again."
     kill -15 $$
  fi
  oldi=$newi
  echo \
   "	...missing `expr $oldi : '.*'` types, doublechecking..."
done

$RM _autotst.$O

cat >_autotst.c <<HERE
#include "$ACONF"
#include "../config.h"
#include <stdio.h>
#ifndef STDLIB_H_MISSING
#include <stdlib.h>
#define INITIAL 60
#else
void*realloc(),*malloc();
#endif
int main()
{ char*p=malloc(1),*q=0;
  size_t len,last,max=BLKSIZ*64;	      /* 1M on non-SMALLHEAP systems */
  int count=0;
  for(last=len=INITIAL;len<=max+INITIAL;len+=BLKSIZ)
   { if(!(p=realloc(p,len)))
	break;
     if(p!=q)
	count++,q=p,fprintf(stderr,"len=%lu p=%p\n",(unsigned long)len,p);
     for(;last<len;last+=1024)		    /* touch at least every new page */
	p[last]=last%127;
   }
  free(q);
  printf("/* %d move%s in %d steps of size %d when reallocing */\n",
	 count,count==1?"":"s",(int)(max/BLKSIZ),BLKSIZ);
  if(BLKSIZ*(10*count+1)>max)
   { puts("#define INEFFICIENTrealloc");
     exit(1);
   }
  exit(0);
}
HERE

echo 'Checking realloc implementation'

if $MAKE _autotst >$DEVNULL 2>&1
 test -f _autotst
then
 _autotst >_autotst.rrr 2>realloc.log
 case "$?" in
 0) cat _autotst.rrr >>$ACONF;;
 1) cat _autotst.rrr >>$ACONF
    echo 'Sorry, repeatedly reallocing is inefficient';;
 *) echo "The test program failed somehow.  Assuming realloc is fine";;
 esac
fi

$RM _autotst.$O _autotst _autotst.rrr

cat >_autotst.c <<HERE
#include "includes.h"
int main(){int i;i=1;
 i+=WIFEXITED(i);
 i+=WIFSTOPPED(i);
 i+=WEXITSTATUS(i);
 i+=WSIGTERM(i);
 return i;}
HERE

echo 'Testing for WIFEXITED(), WIFSTOPPED(), WEXITSTATUS() & WSIGTERM()'
if $MAKE _autotst.$O >_autotst.rrr 2>&1
then
   $FGREP -v include/ <_autotst.rrr >_autotst.$O
   $MV _autotst.$O _autotst.rrr
   grepfor struct '#define WMACROS_NON_POSIX' ||
    grepfor union '#define WMACROS_NON_POSIX'
else
   echo '#define WMACROS_NON_POSIX' >>$ACONF
fi
$RM _autotst.$O _autotst.rrr

cat >_autotst.c <<HERE
#include <pwd.h>
int main()
{ struct passwd*pw=getpwuid(0);
  return (pw->pw_passwd==0)+(pw->pw_class==0)+(pw->pw_gecos==0);
}
HERE

echo 'Testing for various struct passwd members'
$MAKE _autotst.$O >_autotst.rrr 2>&1
grepfor pw_passwd '#define NOpw_passwd'
grepfor pw_class  '#define NOpw_class'
grepfor pw_gecos  '#define NOpw_gecos'
$RM _autotst.$O _autotst.rrr

cat >_autotst.c <<HERE
#include "includes.h"
#ifndef NO_COMSAT
#include "network.h"
#endif
int main(){char a[2];
 endpwent();endgrent();memmove(a,"0",1);bcopy("0",a,1);strcspn(a,"0");
 strtol("0",(char**)0,10);strchr("0",'0');strpbrk(a,"0");rename(a,"0");
 setrgid(0);setegid(0);setregid(0,0);setresgid(0,0,0);opendir("0");
 initgroups("0",0);strstr("0","0");mkdir("0",0);pow(0.,0.);clock();
 waitpid((pid_t)-1,(int*)0,0);ftruncate(0,0);fsync(0);strtod("0.0",(char**)0);
 strncasecmp("0","0",3);strerror(ENOENT);strlcat(a,"0",2);
 bzero(a,2);memset(a,'\0',2);
#ifdef S_ISLNK
 {struct stat stbuf;fstat(0,&stbuf);}
#endif
#ifndef NOuname
 {struct utsname b;uname(&b);}
#endif
#ifndef NO_COMSAT
 gethostbyname("0");getprotobyname(COMSATprotocol);endhostent();endservent();
 endprotoent();
#endif
 _exit(0);
 return 0;}
HERE

echo 'Testing for memmove, strchr, strpbrk, strcspn, strtol, strstr,'
echo '	rename, setrgid, setegid, pow, opendir, mkdir, waitpid, fsync,'
echo '	ftruncate, strtod, strncasecmp, strerror, strlcat,'
echo '	memset, bzero, and _exit'
if $MAKE _autotst.$O >$DEVNULL 2>&1
then
:
else
  echo 2>&1 "Whoeaaa!  There's something fishy going on here."
  echo 2>&1 "You have a look and see if you detect anything uncanny:"
  echo 2>&1 "*******************************************************"
  cat 2>&1 _autotst.rrr
  echo 2>&1 "*******************************************************"
  echo 2>&1 "Your include files seem to be beyond repair <sigh>."
  echo 2>&1 "I give up."
  kill -15 $$
fi
$MAKE _autotst >_autotst.rrr 2>&1
$RM _autotst _autotst.$O

# The simple ones
for func in strcspn strpbrk rename pow mkdir fstat initgroups \
 strtol waitpid ftruncate fsync strtod strncasecmp strlcat memset bzero _exit
do
  grepfor $func "#define NO$func"
done

NOstrerror=no
grepfor strerror "#define NOstrerror" && NOstrerror=yes

grepfor opendir "
#define NOopendir	/* the readdir library does not seem to be available
			   this will slightly affect the way a filenumber is
			   selected in MH-folders by procmail */
"
a=no
grepfor setrgid '#define NOsetrgid' && a=yes
if grepfor setegid '#define NOsetegid' || test $a = yes
then
  grepfor setregid '#define NOsetregid' &&
   grepfor setresgid '#define NOsetresgid'
fi
grepfor strchr '#define strchr(s,c) index(s,c)'
grepfor uname "\
#define NOuname		  \
/* <sys/utsname.h> defines it, the libraries don't */"
grepfor endpwent '#define endpwent()'
grepfor endgrent '#define endgrent()'
if grepfor gethostbyname '#define NO_COMSAT'
then
:
else
  grepfor getprotobyname '#define UDP_protocolno 17'
  grepfor endhostent '#define endhostent()'
  grepfor endservent '#define endservent()'
  grepfor endprotoent '#define endprotoent()'
fi
grepfor strstr '#define SLOWstrstr' ||
 grepfor clock '#define SLOWstrstr'
grepfor memmove '#define NOmemmove' &&
if $FGREP -e bcopy _autotst.rrr >$DEVNULL
then
 echo '#define NObcopy' >>$ACONF

if test $NOstrerror = yes
then
  cat >_autotst.c <<HERE
#include "includes.h"
int main(){
 return puts(sys_errlist[sys_nerr-1]);}
HERE

  echo 'Testing for sys_errlist'
  if $MAKE _autotst.$O >_autotst.rrr 2>&1
  then
    if $MAKE _autotst >_autotst.rrr 2>&1
    then
      echo '' >_autotst.rrr
    fi
  fi
  grepfor sys_errlist '#define NOsys_errlist'
  $RM _autotst _autotst.$O _autotst.rrr
fi

 echo 'Testing for brain damage'
 cat >_autotst.c <<HERE
#include "includes.h"
struct tests{int a,b;};
int main(){
 return offsetof(struct tests,b);}
HERE
 if $MAKE _autotst.$O >$DEVNULL 2>&1
 then
    :
 else
    echo 'Yep, it is'			# ISC chokes on its own offsetof()
    echo '#define oBRAIN_DAMAGE' >>$ACONF
 fi
 $RM _autotst.$O

else

 cat >_autotst.c <<HERE
#include "includes.h"
#define M256	256
#define F33	33
int main(){int j=0,i=M256-1;static char a[M256];
  do a[i]=i;while(i--);
  bcopy(a+F33,a,M256-F33);bcopy(a,a+F33,M256-F33);i=F33-1;
  do j|=a[i]!=(char)(i+F33);while(i--);i=M256-1;
  do j|=a[i]!=(char)i;while(--i!=F33-1);return !j;}
HERE

 echo 'Testing for bcopy handling overlaps'
 $MAKE _autotst >$DEVNULL 2>&1

 if _autotst
 then
   echo 'Sorry, incompetent bcopy, using substitute instead'
   echo '#define NObcopy' >>$ACONF
 fi
 $RM _autotst.$O _autotst
fi
test -f /bin/test && echo "#define GOT_bin_test" >>$ACONF

cat >_autotst.c <<\HERE
#define BENCHSIZE	16384
#define GRANULARITY	64		    /* maximal benchmark granularity */
#include "sublib.c"
#ifndef NO_COMSAT
#include "network.h"					 /* also for ntohs() */
#endif
#undef malloc						     /* from shell.h */
#ifdef BENCHSIZE
#undef strstr						  /* from includes.h */
#undef free						     /* from shell.h */
unsigned long dobench(strstr,iter,haystack)char*(*const strstr)();
 unsigned long iter;const char*const haystack;
{ unsigned long to;
  to=(unsigned long)clock();
  do (*strstr)(haystack,FROM_EXPR);
  while(--iter);
  return (unsigned long)clock()-to;
}
#endif
int main(argc,argv)int argc;const char*argv[];
{ if(argc==1)
   { char*haystack;
#ifdef BENCHSIZE
     if(haystack=malloc(BENCHSIZE))
      { unsigned c1,c2,i;time_t t;
	unsigned long iter,titer,syscnt;
	for(i=c1=c2=0;i<BENCHSIZE-1;i++,c1++,c2++)
	 { haystack[i]='a';
	   if(c1==37)
	      c1=0,haystack[i]='\n';
	   if(c2==51)
	      c2=0,haystack[i]='\n';
	 }
	haystack[i]='\0';
	for(titer=~(unsigned long)0,t=0,iter=1;t<=1&&iter<<1&&iter<titer;)
	 { t=time((time_t*)0);
	   if((syscnt=dobench(strstr,iter<<=1,haystack))&&!~titer)
	      titer=iter*GRANULARITY;
	   t=time((time_t*)0)-t;
	 }
	iter=dobench(sstrstr,iter,haystack);free(haystack);
	if(!syscnt)
	   syscnt=1;
	if(!iter)
	   iter=1;
	printf("\
/* Your system's strstr() is %.2f times %sER than my C-routine */\n",
	 syscnt>=iter?(double)syscnt/iter:(double)iter/syscnt,
	 syscnt>=iter?"SLOW":"FAST");
	if(syscnt>iter+iter/16)		  /* if at least 1.0625 times slower */
	   printf("\
#define SLOWstrstr\t\t\t      /* using my substitute instead */\n");
      }
     else
	printf("/* Insufficient memory to perform the benchmark! */\n");
#endif /* SLOWstrstr */
#ifndef NO_COMSAT
#ifndef UDP_protocolno
     ;{ const struct protoent*p;
	if(p=getprotobyname(COMSATprotocol))
	 { printf("#define UDP_protocolno %d\n",p->p_proto);
#else
     ;{ if(1)
	 {
#endif
	   ;{ const struct servent*serv;
	      if(serv=getservbyname(COMSATservice,COMSATprotocol))
		 printf("#define BIFF_serviceport \"%d\"\n",
		  ntohs(serv->s_port));
	    }
#ifdef AF_INET
	   ;{ const struct hostent*host;
	      if(!strcmp("localhost",COMSAThost)&&
	       (host=gethostbyname(COMSAThost))&&
	       host->h_0addr_list&&host->h_addrtype==AF_INET&&
	       host->h_length)
	       { int j=host->h_length;
		 const unsigned char*ad=(void*)host->h_0addr_list;
		 printf("#define IP_localhost {");
		 printf("%d",*ad++);
		 while(--j)
		    printf(",%d",*ad++);
		 puts("}");
	       }
	    }
#endif /* AF_INET */
	 }
	else
	   puts("#define NO_COMSAT");
      }
#endif /* NO_COMSAT */
     ;{ unsigned long s=(size_t)~0;int bits;
	for(bits=1;s>>=1;bits++);
	if(bits<=16)
	 { puts("#define SMALLHEAP");
	   return 0;
	 }
      }
#ifdef _GUID_T						      /* ISC cc hack */
     ;{ struct passwd*p;
	if(sizeof(int)>sizeof(uid_t)&&(p=getpwnam("root"))&&(*p->pw_dir!='/'||
	 (*p->pw_shell&&!(p->pw_shell)[1])))
	 { puts("#define _GUID_T\ntypedef int uid_t;\ntypedef int gid_t;");
	   goto skipsetrgid;
	 }
      }
#endif
#ifndef NOinitgroups
     if(geteuid()==ROOT_uid)
      { setgid(2);
	if(!setrgid(3)&&(getgid()!=3||getegid()!=2))
	   puts("#define setrgid_BRAIN_DAMAGE");
	else
	 { setuid(2);
	   if(!setgid(3)&&!setgid(2))
	      puts("#define TOGGLE_SGID_OK");
	 }
      }
     else
#ifndef NGROUPS_MAX			 /* is this safeguard really needed? */
#define NGROUPS_MAX	3
#endif				       /* some OSes expect an array of ints? */
      { gid_t groups[NGROUPS_MAX*sizeof(int)/sizeof(gid_t)];unsigned i;
	for(i=getgroups(NGROUPS_MAX,groups);
	    --i<NGROUPS_MAX&&groups[i]==getgid(););
	if(i<NGROUPS_MAX)
	 { setegid(groups[i]);
	   if(!setrgid(groups[i])&&getgid()!=groups[i])
	      puts("#define setrgid_BRAIN_DAMAGE");
	 }
	else
	   puts("#define setrgid_RUNTIME_CHECK");
      }
#endif
skipsetrgid:;
   }
#ifdef DEFsendmail
  if(argc==3)
   { printf("#define SENDMAIL \"%s\"\n",DEFsendmail);
     return 1;
   }
#endif
  if(argc==4)
   { FILE*fp;					      /* in case we are root */
     chown(argv[1],2,getegid());setuid(2);     /* adjust the directory first */
     if(!(fp=fopen(argv[2],"w")))
	goto openerr;				 /* shouldn't happen, really */
     fclose(fp);			   /* always clean up after yourself */
     if(!chown(argv[2],geteuid()==3?4:3,getegid()))
openerr:
	printf("#define CAN_chown\n");
   }
  if(argc>4)
#define MAX_ENVMEM	2048			 /* typical environment size */
#define MAX_ARGMEM	(2048*1024L)	       /* upper limit arguments size */
   { static const char arg[]="e%04u=6789012345";unsigned diff;
     charNUM(num,diff);char**nargv;const char*einfo="";
#define MAXT(type)	(~(type)0>>1)
     sscanf(argv[1],"%u",&diff);  /* what did our previous incarnation want? */
     if(!diff)			   /* first run?  initialise the environment */
      { char*envs,**nenviron,**nenv;
	diff=MAX_ENVMEM/sizeof arg+1;
	if(!(nenviron=malloc(diff*sizeof*environ+MAX_ENVMEM)))
	   goto printit;			      /* oops, panic already */
	envs=(char*)((nenv=nenviron)+diff);
	while(--diff)				       /* put in some colour */
	   sprintf(*nenviron++=envs,arg,diff),envs+=sizeof arg;
	*(environ=nenv)="PATH=.";*nenviron=0;diff=argc;	   /* start doubling */
      }
     if(MAX_ARGMEM/sizeof arg<=argc)			 /* we are satisfied */
      { einfo=" /* soft limit */";		  /* no reason to hog memory */
	goto printit;
      }
     ;{ unsigned narg;
	while(narg=argc+diff+1,		  /* allocate space for the new args */
	     !(nargv=malloc(narg*sizeof*argv+(size_t)diff*sizeof arg)))
	   if(!(diff>>=1))			 /* oops, no space, back off */
	      goto printit;					    /* panic */
	tmemmove(nargv,argv,argc*sizeof*argv);nargv[1]=num;	 /* copy old */
	;{ char**pargv,*args;unsigned i;
	   pargv=nargv+argc;args=(char*)(nargv+narg);i=diff;
	   do
	    { const char*p;			/* and paint in the new ones */
	      for(*pargv++=args,p=arg;*args++= *p++;);
	    }
	   while(--i);
	 }
      }
     for(;;diff>>=1)
      { unsigned newdiff=diff>>1;	    /* take a small step for mankind */
	if(argc==diff)				    /* or shall we boldly go */
	   newdiff=(unsigned)argc<<1;	    /* where no man has gone before? */
	;{ unsigned maxdiff=MAXT(unsigned)-argc;
	   if(newdiff>maxdiff)			 /* that would overflow argc */
	      newdiff=maxdiff;	 /* and we wouldn't want that, would we now? */
	 }
	if(!newdiff)				    /* reductio ad adsurdum? */
	   break;			    /* yes, break off the engagement */
	sprintf(num,"%u",newdiff);nargv[argc+diff]=0;  /* pass on the target */
	execv(argv[0],nargv);					/* jeronimo! */
      }
printit:				  /* we proudly present the findings */
     printf("#define MAX_argc %d%s\n",argc-2,einfo);	     /* of the jury! */
   }
  return EXIT_SUCCESS;
}
HERE

echo "Determining the maximum number of 16 byte arguments execv() takes"

if $MAKE _autotst >$DEVNULL 2>_autotst.rrr &&
   _autotst 0 012345678901234 012345678901234 012345678901234 \
    >>$ACONF 2>>_autotst.rrr
then
:
else
  echo 2>&1 "Whoeaaa!  This actually can't happen."
  echo 2>&1 "You have a look and see if you detect anything uncanny:"
  echo 2>&1 "*******************************************************"
  cat 2>&1 _autotst.rrr
  echo 2>&1 "*******************************************************"
  echo 2>&1 "I suggest you take a look at the definition of LDFLAGS*"
  echo 2>&1 "in the Makefile before you try make again."
  kill -15 $$
fi

$RM _autotst.rrr

echo "Benchmarking your system's strstr() implementation"

_autotst >>$ACONF

found=no

for a in /var/spool/mail /usr/spool/mail /var/mail /usr/mail /spool/mail
do
  test -d $a -a $found != yes &&
   echo '#define MAILSPOOLDIR "'$a'/"' >>$ACONF && found=yes
done
if test $found != yes
then
 echo '#define MAILSPOOLDIR "/var/spool/mail/"' >>$ACONF
 echo Could not find the system-mailbox directory, supplied default.
fi

cat >lookfor <<HERE
for a in /usr/sbin /usr/lib /lib /usr/etc /etc /usr/bin /bin /usr/local/bin \
 /usr/lbin /usr/local/lib /usr/local /usr/.lib /local/bin /sbin
do
 if test -f "\$a/\$1"
 then
    echo '#define SENDMAIL "'"\$a/\$1"'"' >>$ACONF
    exit 0
 fi
done
exit 1
HERE
chmod 0755 lookfor

if _autotst 2 3 >>$ACONF
   test $? != 0 ||
    lookfor sendmail || lookfor smail || lookfor mail #|| lookfor rmail
then
:
else
 echo 'Could not find any mailer.  It should be a mailer accepting at least'
 echo 'one plain destination address as its only argument (any sendmail'
 echo 'compatible mailer will do), and the mail-to-be-sent on stdin.'
 echo 'What is your mailer called?  (You can override this in config.h)'
 read a
 echo "#define SENDMAIL \"$a\"" >>$ACONF
fi

grep '^#define SENDMAIL ".*/sendmail"' $ACONF >$DEVNULL ||
 echo "#define DEFflagsendmail \"\"" >>$ACONF

a=/tmp/_chowntst.$$
$RM -r $a
OLDTESTDIRS="$a $OLDTESTDIRS"
mkdir $a
mkdir $a/__

_autotst $a/__ $a/__/__ 4 >>$ACONF

cat /usr/lib/sendmail.cf /etc/sendmail.cf /etc/mail/sendmail.cf 2>$DEVNULL |
 grep 'Mlocal.*procmail' >$DEVNULL ||
 echo '#define CF_no_procmail_yet' >>$ACONF

cat /usr/lib/sendmail.cf /etc/sendmail.cf /etc/mail/sendmail.cf 2>$DEVNULL |
 grep '^V' >$DEVNULL ||
 echo '#define buggy_SENDMAIL' >>$ACONF

lpath='/bin'
bins="/bin"

for newd in /usr/bin /usr/ucb /usr/5bin $BINDIR /local/bin /usr/local/bin \
 /global/bin /usr/bin/X11 /usr/X*/bin
do
  if test -d $newd
  then
     oldid=`cd $newd; ls -id . .. ../.. 2>&1`
     for oldd in $bins
     do
	test "X`cd $oldd; ls -id . .. ../.. 2>&1`" = "X$oldid" && oldid=found
     done
     test found != "$oldid" && bins="$bins $newd" && lpath="$lpath:$newd"
  fi
done

echo "#define defPATH \"PATH=\$HOME/bin:$lpath\"" >>$ACONF
echo "#define defSPATH \"PATH=$lpath\"" >>$ACONF

sed -n -e 's/^ v\([^ ]*\) .*$/#define PM_VERSION "\1"/p' \
 ../patchlevel.h >>$ACONF

while $FGREP -e "Kernel-locking tests completed." _locktst.rrr >$DEVNULL; \
 test 0 != $?
do
  if test -z "$tailpid"
  then
     echo "Waiting for the kernel-locking tests to finish..."
     exec 9>&2 2>$DEVNULL
     tail -f lock.log &
     tailpid=$!
     exec 2>&9 9>&-
  fi
# if test ! -f _locktst.alive
# then
#    echo >_locktst.alive
#    echo "Waiting for kernel-locking tests to finish..."
# fi
  sleep 4
done
exec 9>&2 2>$DEVNULL
test ! -z "$tailpid" && kill $tailpid && echo "" && echo ""
tailpid=""
wait			# wait now, to prevent a notification message afterward
exec 2>&9 9>&-
echo "Collecting results from kernel-locking tests"
sed -e '/^Kernel-locking tests completed./,$ d' <_locktst.rrr >>$ACONF
set dummy *core*
if test -f $2 -a $nocore = yes
then
  echo "Removing core file (probably from the locking tests)"
  $RM *core*
fi

echo "/* autoconf completed */" >>$ACONF

$RM -r $OLDTESTDIRS $OLDTESTDIRS 2>$DEVNULL
$RM _autotst* _locktst* lookfor grepfor 2>$DEVNULL

echo =============================autoconf.h===================================
cat $ACONF
echo ==========================================================================
